home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / b / b.lha / B / src / bed / mkboot.c < prev    next >
Encoding:
C/C++ Source or Header  |  1988-11-24  |  8.4 KB  |  465 lines

  1. /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
  2. static char rcsid[]= "$Header: mkboot.c,v 1.1 85/08/22 15:44:31 timo Exp $";
  3.  
  4. /*
  5.  * B editor -- Program to create the "boot.h" file (the grammar tables).
  6.  */
  7.  
  8. #include "b.h"
  9. #include "node.h"
  10. #include "gram.h"
  11. #include "tabl.h"
  12.  
  13. #include <ctype.h>
  14.  
  15.  
  16. /*
  17.  * Test whether sym is in the given class.
  18.  */
  19.  
  20. Visible bool
  21. isinclass(sym, ci)
  22.     int sym;
  23.     struct classinfo *ci;
  24. {
  25.     classptr cp;
  26.  
  27.     Assert(ci && ci->c_class);
  28.     if (sym == Hole)
  29.         return !isinclass(Optional, ci);
  30.     for (cp = ci->c_class; *cp; ++cp)
  31.         if (sym == *cp)
  32.             return Yes;
  33.     return No;
  34. }
  35.  
  36.  
  37. main()
  38. {
  39.     int sym;
  40.     int nch;
  41.     struct classinfo **cp;
  42.     struct classinfo *sp;
  43.  
  44.     printf("/* boot.h -- data file for grammar tables. */\n\n");
  45.  
  46.     /* Check the representations.
  47.        The code assumes Optional and Hole are the last symbols
  48.        in the table, i.e. the first processed by the loop. */
  49.  
  50.     for (sym = TABLEN-1; sym >= 0; --sym) {
  51.         if (table[sym].r_symbol != sym) {
  52.             if (sym != Hole && sym != Optional
  53.                     && table[sym].r_symbol == 0)
  54.                 continue; /* Disabled table entry */
  55.             syserr("initgram: table order (%s=%d, should be %d)",
  56.                 table[sym].r_name, table[sym].r_symbol, sym);
  57.         }
  58.         cp = table[sym].r_class;
  59.         for (nch = 0; nch < MAXCHILD && (sp = cp[nch]); ++nch)
  60.             ;
  61.         ckrepr(table[sym].r_repr, nch);
  62.     }
  63.  
  64.     initcodes();
  65.     initclasses();
  66.     dumptable();
  67.     exit(0);
  68. }
  69.  
  70.  
  71. /*
  72.  * Check a representation array (subroutine for initgram).
  73.  */
  74.  
  75. Hidden Procedure
  76. ckrepr(rp, nch)
  77.     string *rp;
  78.     int nch;
  79. {
  80.     string cp;
  81.     int i;
  82.     int ich;
  83.  
  84.     for (ich = 0; ich <= nch; ++ich) {
  85.         cp = rp[ich];
  86.         if (!cp)
  87.             continue;
  88.         for (i = 0; cp[i]; ++i) {
  89.             switch (cp[i]) {
  90.             case '\n':
  91.             case '\r':
  92.                 if (i || ich)
  93.                     syserr("initgram (ckrepr): badly placed \\n/\\r");
  94.                 break;
  95.             case '\t':
  96.             case '\b':
  97.                 if (cp[i+1])
  98.                     syserr("initgram (ckrepr): badly placed \\t/\\b");
  99.                 break;
  100.             default:
  101.                 if (cp[i] < ' ' || cp[i] >= 0177)
  102.                     syserr("initgram (ckrepr): illegal control char");
  103.             }
  104.         }
  105.     }
  106. }
  107.  
  108.  
  109. /*
  110.  * Compaction scheme for characters to save space in grammar tables
  111.  * by combining characters with similar properties (digits, l.c. letters).
  112.  */
  113.  
  114. #define RANGE 128 /* ASCII characters are in {0 .. RANGE-1} */
  115.  
  116. Visible char code_array[RANGE];
  117. Visible char invcode_array[RANGE];
  118. Visible int lastcode;
  119.  
  120. Hidden Procedure
  121. initcodes()
  122. {
  123.     int c;
  124.  
  125.     code_array['\n'] = ++lastcode;
  126.     invcode_array[lastcode] = '\n';
  127.     for (c = ' '; c <= '0'; ++c) {
  128.         code_array[c] = ++lastcode;
  129.         invcode_array[lastcode] = c;
  130.     }
  131.     for (; c <= '9'; ++c)
  132.         code_array[c] = lastcode;
  133.     for (; c <= 'a'; ++c) {
  134.         code_array[c] = ++lastcode;
  135.         invcode_array[lastcode] = c;
  136.     }
  137.     for (; c <= 'z'; ++c)
  138.         code_array[c] = lastcode;
  139.     for (; c < RANGE; ++c) {
  140.         code_array[c] = ++lastcode;
  141.         invcode_array[lastcode] = c;
  142.     }
  143. }
  144.  
  145.  
  146. /*
  147.  * Initialization routine for the 'struct classinfo' stuff.
  148.  *
  149.  * "Suggestion" is skipped:
  150.  * what can be inserted there is not computed from this table.
  151.  */
  152.  
  153. Hidden Procedure
  154. initclasses()
  155. {
  156.     int i;
  157.     int j;
  158.     struct table *tp;
  159.  
  160.     for (i = 0; i < TABLEN; ++i) {
  161.         tp = &table[i];
  162.         if (tp->r_symbol != i || i == Suggestion)
  163.             continue; /* Dead entry */
  164.         for (j = 0; j < MAXCHILD && tp->r_class[j]; ++j) {
  165.             if (!tp->r_class[j]->c_insert)
  166.                 defclass(tp->r_class[j]);
  167.         }
  168.     }
  169. }
  170.  
  171. classptr makelist(); /* Forward */
  172.  
  173. Hidden Procedure
  174. defclass(p)
  175.     struct classinfo *p;
  176. {
  177.     int c;
  178.     struct table *tp;
  179.     classptr cp;
  180.     classptr cp1;
  181.     classelem insert[1024];
  182.     classelem append[1024];
  183.     classelem join[1024];
  184.     int inslen = 0;
  185.     int applen = 0;
  186.     int joinlen = 0;
  187.     string *rp;
  188.     int fw1;
  189.  
  190.     cp = p->c_class;
  191.     Assert(cp);
  192.  
  193.     for (; *cp; ++cp) {
  194.         if (*cp == Optional)
  195.             continue;
  196.         if (*cp >= TABLEN) { /* Insert direct lexical item */
  197.             for (c = 1; c <= lastcode; ++c) {
  198.                 if (maystart(Invcode(c), *cp)) {
  199.                     Assert(inslen+3 < sizeof insert / sizeof insert[0]);
  200.                     insert[inslen] = c;
  201.                     insert[inslen+1] = *cp;
  202.                     inslen += 2;
  203.                 }
  204.             }
  205.             continue;
  206.         }
  207.         tp = &table[*cp];
  208.         rp = tp->r_repr;
  209.         if (!Fw_zero(rp[0])) { /* Insert fixed text */
  210.             c = Code(rp[0][0]);
  211.             Assert(inslen+3 < sizeof insert / sizeof insert[0]);
  212.             insert[inslen] = c;
  213.             insert[inslen+1] = *cp;
  214.             inslen += 2;
  215.             continue;
  216.         }
  217.         Assert(tp->r_class[0]);
  218.         cp1 = tp->r_class[0]->c_class;
  219.         Assert(cp1);
  220.         for (; *cp1; ++cp1) {
  221.             if (*cp1 < TABLEN)
  222.                 continue;
  223.             for (c = 1; c <= lastcode; ++c) { /* Insert indir. lex. items */
  224.                 if (maystart(Invcode(c), *cp1)) {
  225.                     Assert(inslen+3 < sizeof insert / sizeof insert[0]);
  226.                     insert[inslen] = c;
  227.                     insert[inslen+1] = *cp;
  228.                     inslen += 2;
  229.                 }
  230.             }
  231.         }
  232.         fw1 = Fwidth(rp[1]);
  233.         if (fw1) { /* Append */
  234.             c = rp[1][0];
  235.             Assert(c > 0 && c < RANGE);
  236.             if (c == ' ') {
  237.                 c = rp[1][1];
  238.                 if (!c || c == '\b' || c == '\t')
  239.                     c = ' ';
  240.                 else
  241.                     c |= 0200;
  242.             }
  243.             Assert(applen+3 < sizeof append / sizeof append[0]);
  244.             append[applen] = c;
  245.             append[applen+1] = *cp;
  246.             applen += 2;
  247.         }
  248.         if ((!fw1 || fw1 == 1 && rp[1][0] == ' ')
  249.             && tp->r_class[1]) { /* Join */
  250.             Assert(joinlen+3 < sizeof join / sizeof join[0]);
  251.             join[joinlen] = 1 + fw1;
  252.             join[joinlen+1] = *cp;
  253.             joinlen += 2;
  254.         }
  255.     }
  256.  
  257.     Assert(inslen); /* Dead alley */
  258.     insert[inslen] = 0;
  259.     p->c_insert = makelist(insert, inslen + 1);
  260.     if (applen) {
  261.         append[applen] = 0;
  262.         p->c_append = makelist(append, applen + 1);
  263.     }
  264.     if (joinlen) {
  265.         join[joinlen] = 0;
  266.         p->c_join = makelist(join, joinlen + 1);
  267.     }
  268. }
  269.  
  270. Hidden classptr
  271. makelist(list, len)
  272.     classptr list;
  273.     int len;
  274. {
  275.     classptr cp =
  276.         (classptr) malloc((unsigned) (len*sizeof(classelem)));
  277.     int i;
  278.  
  279.     if (!cp)
  280.         syserr("makelist: malloc");
  281.     for (i = 0; i < len; ++i, ++list)
  282.         cp[i] = *list;
  283. #ifndef NDEBUG
  284.     if (index(cp, '\0') != cp+len-1)
  285.         printf("makelist: zero in string!\n");
  286. #endif
  287.     return cp;
  288. }
  289.  
  290. #define MAXLOOKUP 1000
  291.  
  292. Hidden struct classinfo **known;
  293. Hidden int nknown;
  294.  
  295. Hidden Procedure
  296. dumptable()
  297. {
  298.     int sym;
  299.  
  300.     getclassinfos();
  301.     printf("Hidden struct table b_grammar[%d] = {\n", TABLEN);
  302.     for (sym= 0; sym < TABLEN; ++sym)
  303.         dumpentry(table+sym);
  304.     printf("};\n");
  305.     free(known);
  306. }
  307.  
  308. Hidden Procedure
  309. getclassinfos()
  310. {
  311.     int sym, k;
  312.  
  313.     known= (struct classinfo **) malloc(MAXLOOKUP * sizeof(struct classinfo*));
  314.     if (known == NULL)
  315.         syserr("getclassinfos: can't malloc 'known' array");
  316.     nknown= 0;
  317.     printf("Hidden struct classinfo cl[] = {\n");
  318.     for (sym= 0; sym < TABLEN; ++sym) {
  319.         for (k= 0; k < MAXCHILD; ++k)
  320.             lookup(table[sym].r_class[k]);
  321.     }
  322.     printf("};\n\n");
  323. }
  324.  
  325. Hidden int
  326. lookup(ci)
  327.     struct classinfo *ci;
  328. {
  329.     int k;
  330.  
  331.     if (ci == NULL)
  332.         return -1;
  333.     for (k= 0; k < nknown; ++k) {
  334.         if (known[k] == ci)
  335.             return k;
  336.     }
  337.     if (k < MAXLOOKUP) {
  338.         ++nknown;
  339.         known[k]= ci;
  340.         printf("/*%d*/", k);
  341.         dumpclassinfo(ci);
  342.     }
  343. }
  344.  
  345. Hidden Procedure
  346. dumpclassinfo(ci)
  347.     struct classinfo *ci;
  348. {
  349.     printf("\t{");
  350.     dumpstring(ci->c_class);
  351.     printf("\n\t");
  352.     dumpstring(ci->c_insert);
  353.     printf("\n\t");
  354.     dumpstring(ci->c_append);
  355.     printf("\n\t");
  356.     dumpstring(ci->c_join);
  357.     printf("},\n");
  358. }
  359.  
  360. Hidden Procedure
  361. dumpentry(p)
  362.     struct table *p;
  363. {
  364.     int k;
  365.  
  366.     printf("\t{%2d, ", p->r_symbol);
  367.     dumpstring(p->r_name);
  368.     printf(" {");
  369.     for (k= 0; k <= MAXCHILD; ++k)
  370.         dumpstring(p->r_repr[k]);
  371.     printf("}, {");
  372.     for (k= 0; k < MAXCHILD; ++k)
  373.         refclassinfo(p->r_class[k]);
  374.     printf("}, 0},\n");
  375. }
  376.  
  377. Hidden Procedure
  378. dumpstring(s)
  379.     string s;
  380. {
  381.     char c;
  382.  
  383.     if (s == NULL) {
  384.         printf("0, ");
  385.         return;
  386.     }
  387.     printf("\"");
  388.     for (; (c= *s) != '\0'; ++s) {
  389.         if (c >= ' ' && c < 0177) {
  390.             if (c == '\\' || c == '"')
  391.                 printf("\\");
  392.             printf("%c", c);
  393.         }
  394.         else if (c == '\t')
  395.             printf("\\t");
  396.         else if (c == '\b')
  397.             printf("\\b");
  398.         else
  399.             printf("\\%03o", c&0377);
  400.     }
  401.     printf("\", ");
  402. }
  403.  
  404. Hidden Procedure
  405. refclassinfo(ci)
  406.     struct classinfo ci;
  407. {
  408.     int k= lookup(ci);
  409.  
  410.     if (k >= 0)
  411.         printf("&cl[%d], ", k);
  412.     else
  413.         printf("0, ");
  414. }
  415.  
  416.  
  417. /*
  418.  * Yield the width of a piece of fixed text as found in a node's repr,
  419.  * excluding \b or \t.  If \n or \r is found, -1 is returned.
  420.  * It assumes that \n or \r only occur as first
  421.  * character, and \b or \t only as last.
  422.  */
  423.  
  424. Visible int
  425. fwidth(str)
  426.     register string str;
  427. {
  428.     register int c;
  429.     register int n = 0;
  430.  
  431.     if (!str)
  432.         return 0;
  433.     c = str[0];
  434.     if (c == '\r' || c == '\n')
  435.         return -1;
  436.     for (; c; c = *++str)
  437.         ++n;
  438.     if (n > 0) {
  439.         c = str[-1];
  440.         if (c == '\t' || c == '\b')
  441.             --n;
  442.     }
  443.     return n;
  444. }
  445.  
  446.  
  447. Visible Procedure
  448. syserr(fmt, a1, a2, a3, a4, a5)
  449.     string fmt;
  450. {
  451.     fprintf(stderr, "mkboot system error:\n");
  452.     fprintf(stderr, fmt, a1, a2, a3, a4, a5);
  453.     fprintf(stderr, "\n");
  454.     exit(1);
  455. }
  456.  
  457.  
  458. Visible Procedure
  459. asserr(file, line)
  460.     string file;
  461.     int line;
  462. {
  463.     syserr("assertion error: %s, line %d", file, line);
  464. }
  465.